# -*- coding: utf-8 -*-
# created on 2016/6/24

from mathsolver.functions.root.jiefangchenzu import JieFangChenZu
from mathsolver.functions.root.jiefangchen import JieFangChen
from mathsolver.functions.base import *
from sympy.abc import x, y
from sympy import S, solveset, Eq, Symbol
from mathsolver.functions.sympy_utils import default_symbol, get_all_child
from mathsolver.functions.shuyushi.shuyushi import DaiRu
from sympy.core.function import UndefinedFunction


class HanShuUpdate(BaseFunction):
    def solver(self, *args):
        func = args[0]
        known_func = self.search(func.name)
        if known_func is None:
            if len(args) > 1:
                cond = args[1]
                func.cond += cond.get_cond()
            self.output.append(func)
        elif isinstance(known_func.expression, list):
            for expression in known_func.expression:
                main = expression["main"]
                ineq = expression["inequality"][0]
                assert isinstance(ineq, list), "inequality not found"
                eq = Eq(main, func.expression)
                if eq is True:
                    self.output.append(BaseIneq(ineq))
                elif eq is not False:
                    self.output.append(BaseIneqs([[main, func.expression], ineq]))
        else:
            expr = known_func.expression.subs({known_func.var: func.var})
            if len((expr - func.expression).free_symbols) == 1:
                self.steps.append(["将%s代入%s得，" % (new_latex(func.var), known_func.printing()), new_latex(expr)])
                stepsolver = JieFangChen().solver(BaseEq([expr, func.expression]))
                self.append(stepsolver)
            else:
                known_func.update(func.value)
                if known_func.expression:
                    symbols = known_func.expression.free_symbols
                    symbols.remove(known_func.var)
                    num_eqs = len(known_func.values)
                    if len(symbols) <= num_eqs:
                        eqs = BaseEqs([[known_func.expression.subs({known_func.var: k}), v] for k, v in
                                       known_func.values.items()])
                        try:
                            stepsolver = JieFangChenZu().solver(eqs)
                            self.append(stepsolver)
                        except Exception:
                            pass
        return self


class HanShuFunEqUpdate(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        funcs = get_all_child(f1 - f2, lambda xx: isinstance(type(xx), UndefinedFunction))
        names = [str(func)[0] for func in funcs]
        assert len(set(names)) == 1

        func = self.search(names[0])
        if func is None:
            func = BaseFunc({"var": "x", "type": "", "name": names[0]})

        func.constrain = Eq(f1, f2)
        self.output.append(func)
        return self


# 点在函数图像上求参
class HanShuGuoDian(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        assert str(f1) in ["y", ""], "Not a function!"

        v1, v2 = args[1].sympify()
        value = {y: v1, x: v2}

        new_f1 = f1.subs(value)
        new_f2 = f2.subs(value)

        self.steps.append(
            ["因为函数%s过点%s" % (self.output_eq([f1, f2]), args[1].printing()), self.output_eq([new_f1, new_f2])])
        self.output.append(BaseEq([new_f1, new_f2]))
        self.label.add("点在函数图像上求参")
        return self


# 点在函数图像上求参
class HanShuGuoYuanDian(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        assert str(f1) in ["y", ""], "Not a function!"

        value = {y: 0, x: 0}

        new_f1 = f1.subs(value)
        new_f2 = f2.subs(value)

        self.steps.append(["因为函数过点原点，所以", self.output_eq([new_f1, new_f2])])
        self.output.append(BaseEq([new_f1, new_f2]))
        self.label.add("点在函数图像上求参")
        return self


# 点所在象限问题
class HanShuOnXiangXian(BaseFunction):
    def solver(self, *args):
        p1, p2 = args[0].sympify()
        text = args[1]
        ineqs = []

        if "第一" in text:
            ineqs.append([p1, ">", S.Zero])
            ineqs.append([p2, ">", S.Zero])

        elif "第二" in text:
            ineqs.append([p1, "<", S.Zero])
            ineqs.append([p2, ">", S.Zero])

        elif "第三" in text:
            ineqs.append([p1, "<", S.Zero])
            ineqs.append([p2, "<", S.Zero])

        elif "第四" in text:
            ineqs.append([p1, ">", S.Zero])
            ineqs.append([p2, "<", S.Zero])

        ineqs = [ineq for ineq in ineqs if len(ineq[0].free_symbols) > 0]
        if len(ineqs) == 1:
            self.steps.append(["由题意得：", self.output_eq(ineqs[0])])
            self.output.append(BaseIneq(ineqs[0]))
        elif len(ineqs) > 1:
            self.steps.append(["由题意得：", self.output_eqs(ineqs)])
            self.output.append(BaseIneqs(ineqs))
        else:
            raise ValueError
        self.label.add("点所在象限问题")
        return self


class HanShuAxisJiaoDian(BaseFunction):
    def solver(self, *args):
        f1 = Symbol("y")
        f2 = args[0].expression
        symbol = default_symbol(f2)
        if isinstance(args[1], BaseAxis):
            axis = args[1].value
            assert str(f1) in ["y", ""], "Not a function!"
            if "x轴" == axis:
                x_v = solveset(f2, x)
                self.steps.append(["因为函数%s与x轴相交, 所以" % self.output_eq([f1, f2]), self.output_eq([y, S.Zero])])
                self.steps.append(["即", self.output_eq([f2, S.Zero])])
                self.steps.append(["解得", self.output_answer({x: x_v})])
                points = [BasePoint([v, S.Zero]) for v in x_v]
                self.output += points
                self.steps.append(["", "函数与x轴的交点坐标为%s" % ",".join([point.printing() for point in points])])
                self.label.add("求函数与x轴的交点")
            elif "y轴" == axis:
                y_v = f2.subs({x: S.Zero})
                self.steps.append(["", "因为函数%s与y轴相交,所以" % self.output_eq([f1, f2])])
                self.steps.append(["", self.output_eq([symbol, S.Zero])])
                self.steps.append(["", "代入函数，得"])
                self.steps.append(["", self.output_eq([f1, y_v])])
                point = BasePoint([S.Zero, y_v])
                self.output.append(point)
                self.steps.append(["", "函数与y轴的交点坐标为%s" % point.printing()])
                self.label.add("求函数与y轴的交点")
            else:
                raise ValueError
        elif isinstance(args[1], BaseEq):
            f3, f4 = args[1].sympify()
            answer = solveset(Eq(f2, f4), x)
            self.steps.append(["", "依题意，得"])
            self.steps.append(["", self.output_eqs([[f1, f2], [f3, f4]])])
            self.steps.append(["", "解得"])
            solutions = JieFangChenZu().solver(BaseEqs([(f1, f2), (f3, f4)])).output
            self.steps.append(["", self.output_jies(solutions[0].value)])
            self.steps.append(["", "交点坐标为"])
            for ans in answer:
                y_v = f2.subs({x: ans})
                point = BasePoint([ans, y_v])
                self.steps.append(["", point.printing()])
                self.output.append(point)
            self.label.add("求两函数的交点")
        else:
            raise ValueError("unexpected input type")
        return self


# 代入法求函数值
class HanShuDaiRu(BaseFunction):
    def solver(self, *args):
        n1, f1, f2 = args[0].name, args[0].var, args[0].expression
        n2, value = args[1].name, args[1].var
        t = Symbol('t')
        assert n1 == n2
        if str(f1) != "x":
            self.steps.append(["", "令%s = %s, 得" % (new_latex(f1), t)])
            answer1 = solveset(f1 - t, x)
            answer1 = {x: list(answer1)}
            self.steps.append(["", self.output_answer(answer1)])
            res1 = DaiRu().solver(BasePoly(f2), BaseSymbolValue(answer1))
            f3 = res1.output[0].value
            self.output = res1.output
            self.steps.append(["", "所以，f(t) "])
            self.steps += res1.steps[1:]
            self.steps.append(["", "把 %s 换成 %s, 得" % (t, new_latex(value))])
            answer2 = {t: [value]}
            res2 = DaiRu().solver(BasePoly(f3), BaseSymbolValue(answer2))
            self.steps.append(["", args[1].printing()])
            self.steps += res2.steps[1:]
            self.output = res2.output
            self.label.add("代入法求函数解析式")
        else:
            answer = {x: [value]}
            res = DaiRu().solver(BasePoly(f2), BaseSymbolValue(answer))
            self.steps.append(["", args[1].printing()])
            self.steps += res.steps[1:]
            self.output = res.output
            self.label.add("代入法求函数值")
        return self


# 待定系数法求参问题
class HanShuPass(BaseFunction):
    def solver(self, *args):
        f1 = Symbol("y")
        f2 = args[0].expression
        points = args[1].sympify()
        eqs = []
        for p1, p2 in points:
            new_f1 = f1.subs({x: p1, y: p2})
            new_f2 = f2.subs({x: p1, y: p2})
            eqs.append([new_f1, new_f2])

        self.steps.append(["将%s直接带入函数得:" % args[1].printing(), self.output_eqs(eqs)])
        self.output.append(BaseEqs(eqs))
        self.label.add("待定系数法求参问题")
        return self


if __name__ == '__main__':
    pass
